package main

import (
	"fmt"
)

// 管道的用法
// 1) 管道放值得时候不允许超过最大长度会报错dead lock
// 2) 管道如果没数据还继续取值会报错dead lock
// 3) 管道实际上就是一个先进先出的FIFO队列而且是线程安全的
// 4) 管道只能存放指定的数据类型
func main() {

	// 1. 创建channel 方式
	var intChan chan int = make(chan int, 3) // 创建容量为3的管道，存放int类型
	// var writeIntChan chan<- int              // 只写的channel
	// var readIntChan <-chan int               // 只读的channel

	// intChan 存放的是地址，该地址就是管道的内存地址
	fmt.Printf("intChan = %v, &intChan = %v \n", intChan, &intChan)
	//intChan = 0xc000090080, &intChan = 0xc0000060281

	// 放值
	intChan <- 1
	intChan <- 2
	intChan <- 3

	// 取值
	for len(intChan) > 0 {
		fmt.Println(<-intChan) // 取值
	}

	fmt.Println("************关闭管道***************")
	// 2. 遍历channel方式
	/*
		被关闭的管道不允许写入数据，只允许读数据，
		在读取的时候没有使用协程的情况下：
			使用for range遍历管道的时候必须先关闭管道，否则报错dead lock，因为关闭后在管道会有一个标志位
	*/
	intChan <- 1
	intChan <- 2
	intChan <- 3
	close(intChan) // 使用 for range 之前必须关闭，否则会阻塞当前
	for v := range intChan {
		fmt.Println(v)
	}

	v, ok := <-intChan // 对于关闭后并且取值完的管道 ok 值为 false
	if ok {
		fmt.Println("取值成功！", v) // 取值失败！
	} else {
		fmt.Println("取值失败！")
	}

}
